home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Skunkware 5
/
Skunkware 5.iso
/
src
/
X11
/
xgrabsc
/
xgrabsc.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-05-09
|
22KB
|
929 lines
/*========================================================================
*
* Name - xgrabsc.c
*
* ccs version: 1.31
*
* ccsid: @(#)xgrabsc.c 1.31 - 06/28/93 09:13:50
* from: ccs/s.xgrabsc.c
* date: 06/28/93 09:14:49
*
* Copyright (c) 1990-93 Bruce Schuchardt.
* Read the file cpyright.h for full copyright information.
*
* XmuClientWindow and TryChildren are Copyright 1989 by the Massachusetts
* Institute of Technology
*
* Permission to use, copy, modify, and distribute this [XmuClientWindow]
* software and its
* documentation for any purpose and without fee is hereby granted, provided
* that the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting
* documentation, and that the name of M.I.T. not be used in advertising
* or publicity pertaining to distribution of the software without specific,
* written prior permission. M.I.T. makes no representations about the
* suitability of this software for any purpose. It is provided "as is"
* without express or implied warranty.
*
* Description:
*
* xgrabsc - grab screen images and store in files
*
*========================================================================
*/
#if defined(__hpux)
/* the folks at HP have decided to make things more difficult
*/
#define XLIB_ILLEGAL_ACCESS
#endif
#include "cpyright.h"
#include "patchlevel.h"
#include "config.h"
#include "checkvm.h"
#include "cmdopts.h"
#include <stdio.h>
#include <X11/Xos.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/cursorfont.h>
#include <X11/Xatom.h>
#ifdef VMS
#include "XWDFile.h"
#else
#include <X11/XWDFile.h>
#endif /* VMS */
#ifndef CARD32
#include <X11/Xmd.h>
#endif
#ifndef NO_VIRTUAL_WINDOW
#include "virtual.h"
#endif
#define MAX_CELLS 256
#define TRUE 1
#define FALSE 0
typedef enum {
NO_DITHER=0,
FS_DITHER,
MATRIX_DITHER,
MATRIX_HALFTONE,
MAP_BW
} ditherType;
typedef unsigned char byte;
typedef unsigned long dw;
typedef unsigned int word;
typedef struct {
XImage *ximage;
word numcells;
word red[MAX_CELLS], green[MAX_CELLS], blue[MAX_CELLS];
byte used[MAX_CELLS];
} imageInfo;
typedef enum {
sourceRect,
sourceRoot,
sourceId,
sourceWd,
sourceKey,
sourceCoords
} sourceType;
typedef enum {
puzzleFormat,
psFormat,
simpleFormat,
xwdFormat,
pixmapFormat
} formatType;
#ifdef BCOPY
#ifdef MEMCPY
#undef MEMCPY
#endif
#define memcpy(x,y,c) bcopy(y,x,c)
#define memset(x,c) bzero(x,c) /* well, I only use it for zeroing out stuff */
#endif
#ifdef MEMCPY
char *memcpy();
char *memset();
#endif
#ifdef VMS
#define rindex strrchr
#endif
static Display *hDisplay;
static int hScreen;
static Window hRoot, vRoot;
static int displayCells;
static char *programName;
static char imageName[64];
static char *version = XGRABSC_VERSION;
static int patchLevel = XGRABSC_PATCHLEVEL;
static int verbose;
static word nr[MAX_CELLS], ng[MAX_CELLS], nb[MAX_CELLS];
static char hexdigits[] = "0123456789abcdef";
static double pageWidth = PAPER_WIDTH;
static double pageHeight = PAPER_HEIGHT;
static double horizMargin = HORIZ_MARGIN;
static double vertMargin = VERT_MARGIN;
static double horizInset = PAPER_WIDTH - HORIZ_MARGIN - HORIZ_MARGIN;
static double vertInset = PAPER_HEIGHT - VERT_MARGIN - VERT_MARGIN;
static char *outfileName;
ditherType DitherKind;
int Halftone;
int ForceBitmap;
static int needColorImageProc;
/* most functions have been moved to seperate source include files */
#include "process.hc" /* color processing */
#include "get.hc" /* get images */
#include "mem.hc" /* memcpy, memset */
#include "convert.hc" /* color->bw conversion */
#include "write.hc" /* output functions */
static Window xgTryChildren();
/* versions of XmuGetClientWindow and screenNumberOfScreen.
* GetClientWindow is used so Xmu need not be linked (causes problems on
* some platforms and configurations if Xt is not used)
* ScreenNumberOfScreen is used because some X implementations do not
* include this function (HP in particular).
*
* The following three functions are from the X11R4 MIT distribution and
* are copyrighted by MIT (see the file header)
*/
static Window GetClientWindow (win)
Window win;
{
Atom WM_STATE;
Atom type = None;
int format;
unsigned long nitems, after;
unsigned char *data;
Window inf;
WM_STATE = XInternAtom(hDisplay, "WM_STATE", True);
if (!WM_STATE)
return win;
XGetWindowProperty(hDisplay, win, WM_STATE, 0, 0, False, AnyPropertyType,
&type, &format, &nitems, &after, &data);
if (type)
return win;
inf = xgTryChildren(win, WM_STATE);
if (!inf)
inf = win;
return inf;
}
static Window xgTryChildren (win, WM_STATE)
Window win;
Atom WM_STATE;
{
Window root, parent;
Window *children;
unsigned int nchildren;
unsigned int i;
Atom type = None;
int format;
unsigned long nitems, after;
unsigned char *data;
Window inf = 0;
if (!XQueryTree(hDisplay, win, &root, &parent, &children, &nchildren))
return 0;
for (i = 0; !inf && (i < nchildren); i++) {
XGetWindowProperty(hDisplay, children[i], WM_STATE, 0, 0, False,
AnyPropertyType, &type, &format, &nitems,
&after, &data);
if (type)
inf = children[i];
}
for (i = 0; !inf && (i < nchildren); i++)
inf = xgTryChildren(children[i], WM_STATE);
if (children) XFree((char *)children);
return inf;
}
int ScreenNumberOfScreen (scr)
register Screen *scr;
{
register Display *dpy = scr->display;
register Screen *dpyscr = dpy->screens;
register int i;
for (i = 0; i < dpy->nscreens; i++, dpyscr++) {
if (scr == dpyscr) return i;
}
return -1;
}
xgrabsc(argc, argv, env)
int argc;
char *argv[]; /* must have at least argv[0] == programName */
char *env;
{
char *args[100], *arg;
extern char *optarg;
FILE *outfile;
XRectangle xrect;
XWindowAttributes xwa;
imageInfo image;
int argn, argi, polarity;
int cmdi, cmdargi;
int doAnd;
int doOr;
int doReverse;
int depth;
int noBell;
int psColor;
int brighten;
int grabServer;
int compress;
int sleepSeconds;
int postSelectSleepSeconds;
int andBits;
int orBits;
int encapsulate;
Window sourceWindow, childWindow, clientWindow, wmWindow, ignored;
char *ptr;
char *display;
int i, x, y;
int brightenFactor;
sourceType source;
formatType outputFormat;
int xpmFormat;
int landscape;
int binary;
int borders;
int checkLimits;
int preview;
int onlyEpsi;
int xwdxy;
outfile = stdout;
outfileName = NULL;
display = NULL;
programName = argv[0];
noBell = FALSE;
brighten = FALSE;
compress = TRUE;
DitherKind = NO_DITHER;
doAnd = FALSE;
doOr = FALSE;
doReverse = FALSE;
encapsulate = FALSE;
ForceBitmap = FALSE;
grabServer = TRUE;
Halftone = FALSE;
landscape = FALSE;
binary = FALSE;
sleepSeconds = 0;
postSelectSleepSeconds = 0;
verbose = FALSE;
borders = TRUE;
#ifdef NO_PRINTER_MEMORY_CHECKS
checkLimits = FALSE;
#else
checkLimits = TRUE;
#endif
preview = FALSE;
needColorImageProc = DEFAULT_NEED_COLORIMAGE_PROC;
source = sourceRect;
outputFormat = psFormat;
psColor = FALSE;
onlyEpsi = FALSE;
xwdxy = FALSE;
/* merge environment options and command line options */
args[0] = programName;
if (env != NULL) {
args[1] = env;
for (argn=2; argn<100 &&
(args[argn]=(char *)strchr(args[argn-1], ' ')) != NULL;
argn++) {
/* remove leading white space */
while (*args[argn] == ' ' || *args[argn] == 9) {
*(args[argn]) = '\0';
args[argn]++;
}
if (*args[argn] == '|' || *args[argn] == '>') /* dbx leaves these in the cmd line */
break;
}
}
else
argn = 1;
for (i=1; i<argc && argn<100; argn++, i++)
args[argn] = argv[i];
for (argi=1; argi<argn; argi++) {
arg = args[argi];
polarity = 1;
if (arg[0] == '-') {
arg++;
if (arg[0] == '-') {
arg++;
polarity = 0;
}
else if (arg[0] == 'n' && arg[1] == 'o') {
arg += 2;
polarity = 0;
}
}
for (cmdi=0; cmdi<numCmds; cmdi++) {
if (strcmp(arg, commands[cmdi].userstr) == 0)
break;
}
if (cmdi >= numCmds) {
fprintf(stderr, "%s: unknown option '%s'\n", programName, arg);
exit(3);
}
cmdargi = argi+1;
argi += commands[cmdi].numargs;
if (argi >= argn) {
fprintf(stderr, "%s: not enough arguments for '%s'\n", programName, arg);
exit(3);
}
switch (commands[cmdi].command) {
case CMD_DISPLAY:
display = args[cmdargi];
break;
case CMD_BELL:
noBell = !polarity;
break;
case CMD_GRABSERVER:
grabServer = polarity;
break;
case CMD_OUTPUT:
outfileName = args[cmdargi];
break;
case CMD_PRESLEEP:
sleepSeconds = atoi(args[cmdargi]);
if (sleepSeconds < 0) sleepSeconds = 0;
break;
case CMD_POSTSLEEP:
postSelectSleepSeconds = atoi(args[cmdargi]);
if (postSelectSleepSeconds < 0) postSelectSleepSeconds = 0;
break;
case CMD_VERBOSE:
verbose = polarity;
break;
case CMD_BORDERS:
borders = polarity;
break;
case CMD_NOBORDERS:
borders = !polarity;
break;
case CMD_SOURCE_KEY:
source = sourceKey;
grabServer = FALSE;
break;
case CMD_SOURCE_COORDS:
{ short w,h,x,y;
source = sourceCoords;
sscanf(args[cmdargi], "%ix%i+%i+%i", &w, &h, &x, &y);
xrect.width = w;
xrect.height = h;
xrect.x = x;
xrect.y = y;
break;
}
case CMD_SOURCE_ID:
source = sourceId;
sourceWindow = 0;
if (!sscanf(args[cmdargi], "%ix", &sourceWindow)) {
fprintf(stderr, "%s: invalid window id '%s'\n", programName, args[cmdargi]);
exit(3);
}
break;
case CMD_SOURCE_RECT:
source = sourceRect;
break;
case CMD_SOURCE_ROOT:
source = sourceRoot;
break;
case CMD_SOURCE_WD:
source = sourceWd;
break;
case CMD_AND:
doAnd = polarity;
if (doAnd)
andBits = atoi(args[cmdargi]);
break;
case CMD_OR:
doOr = polarity;
if (doOr)
orBits = atoi(args[cmdargi]);
break;
case CMD_NOT:
doReverse = polarity;
break;
case CMD_BRIGHTEN:
brighten = polarity;
if (brighten) {
brightenFactor = atoi(args[cmdargi]);
if (brightenFactor <= 0) {
fprintf(stderr, "%s: brightening factor must be a positive number\n",
programName);
exit(3);
}
if (brightenFactor != 100)
brighten = TRUE;
else
brighten = FALSE;
}
break;
case CMD_DITHER_MAP:
ForceBitmap = TRUE;
Halftone = FALSE;
break;
case CMD_DITHER_MATRIX:
DitherKind = MATRIX_DITHER;
Halftone = TRUE;
ForceBitmap = FALSE;
break;
case CMD_DITHER_FS:
if (!polarity) {
DitherKind = NO_DITHER;
Halftone = ForceBitmap = FALSE;
}
else {
DitherKind = FS_DITHER;
Halftone = TRUE;
ForceBitmap = FALSE;
}
break;
case CMD_DITHER_HALFTONE:
DitherKind = MATRIX_HALFTONE;
Halftone = TRUE;
ForceBitmap = FALSE;
break;
case CMD_DITHER_NONE:
DitherKind = NO_DITHER;
Halftone = ForceBitmap = FALSE;
break;
case CMD_OUTPUT_PS:
psColor = FALSE;
outputFormat = psFormat;
break;
case CMD_OUTPUT_CPS:
psColor = polarity;
outputFormat = psFormat;
break;
case CMD_OUTPUT_SIMPLE:
outputFormat = simpleFormat;
break;
case CMD_OUTPUT_XWD:
outputFormat = xwdFormat;
xwdxy = FALSE;
break;
case CMD_OUTPUT_XWDXY:
outputFormat = xwdFormat;
xwdxy = TRUE;
break;
case CMD_OUTPUT_PIXMAP:
xpmFormat = 1;
outputFormat = pixmapFormat;
break;
case CMD_OUTPUT_XPM2:
if (polarity) xpmFormat = 2;
else if (xpmFormat == 2) xpmFormat = 1;
outputFormat = pixmapFormat;
break;
case CMD_OUTPUT_XPM3:
if (polarity) xpmFormat = 3;
else if (xpmFormat == 3) xpmFormat = 1;
outputFormat = pixmapFormat;
break;
case CMD_OUTPUT_PUZZLE:
outputFormat = puzzleFormat;
break;
case CMD_LANDSCAPE:
landscape = polarity;
outputFormat = psFormat;
break;
case CMD_BIN:
binary = polarity;
outputFormat = psFormat;
break;
case CMD_COMPRESS:
compress = polarity;
outputFormat = psFormat;
break;
case CMD_EPS:
encapsulate = polarity;
outputFormat = psFormat;
break;
case CMD_PREVIEWONLY:
onlyEpsi = polarity;
preview = polarity;
outputFormat = psFormat;
break;
case CMD_LIMIT:
checkLimits = polarity;
outputFormat = psFormat;
break;
case CMD_PREVIEW:
preview = polarity;
outputFormat = psFormat;
break;
case CMD_PAGE:
outputFormat = psFormat;
sscanf(args[cmdargi], "%lfx%lf-%lf-%lf",
&pageWidth, &pageHeight, &horizMargin, &vertMargin);
horizInset = pageWidth - horizMargin - horizMargin;
vertInset = pageHeight - vertMargin - vertMargin;
break;
case CMD_COLORPROC:
outputFormat = psFormat;
needColorImageProc = polarity;
break;
}
}
if (verbose) {
fprintf(stderr, "%s: xgrabsc version %s\n", programName, version);
fprintf(stderr, "%s: patchlevel %d\n", programName, patchLevel);
fprintf(stderr, "%s: %s\n\n", programName, Copyright);
}
if (!display) display = (char *)getenv("DISPLAY");
hDisplay = XOpenDisplay(display);
if (!hDisplay) {
fprintf(stderr, "%s: could not open X display\n", programName);
exit(3);
}
hScreen = DefaultScreen(hDisplay);
hRoot = DefaultRootWindow(hDisplay);
#ifndef NO_VIRTUAL_WINDOW
vRoot = VirtualRootWindow(hDisplay, hScreen);
#else
vRoot = hRoot;
#endif
depth = DefaultDepth(hDisplay, hScreen);
if (DisplayCells(hDisplay, hScreen) > MAX_CELLS) {
fprintf(stderr, "%s: color table is too big for this program\n",
programName);
XCloseDisplay(hDisplay);
exit(3);
}
/* sleep if asked to do so */
if (sleepSeconds)
sleep(sleepSeconds);
/* grab the screen if asked to do so */
if (grabServer)
XGrabServer(hDisplay);
if (source != sourceId)
sourceWindow = hRoot;
childWindow = (Window)NULL;
switch (source) {
case sourceKey:
childWindow =
#ifdef SELECTION_MASK
getWindowWhenKeyIsPressed(SELECTION_MASK)
#else
getWindowWhenKeyIsPressed(ControlMask);
#endif
if (!childWindow) {
fprintf(stderr, "%s: unable to find source window\n", programName);
XCloseDisplay(hDisplay);
exit(3);
}
break;
case sourceCoords:
/* already got the xrect in the command line processing section */
break;
case sourceId:
childWindow = sourceWindow;
break;
case sourceWd:
/* grab the image from the root window so menus will show up on top
* of the window */
childWindow=getWindow();
if (!childWindow) {
fprintf(stderr, "%s: unable to find source window\n", programName);
XCloseDisplay(hDisplay);
exit(3);
}
break;
case sourceRoot:
xrect.x = xrect.y = 0;
xrect.width = DisplayWidth(hDisplay, hScreen);
xrect.height = DisplayHeight(hDisplay, hScreen);
break;
case sourceRect:
default:
if (!getRectangle(&xrect)) {
XCloseDisplay(hDisplay);
exit(3);
}
break;
}
clientWindow = (Window)NULL;
if (!borders &&
(source == sourceKey || source == sourceWd || source == sourceId) &&
childWindow != hRoot) {
/* look for a different client window */
clientWindow = GetClientWindow(childWindow);
if (clientWindow && clientWindow != childWindow) {
if (verbose)
fprintf(stderr, "%s: found subwindow 0x%x\n", programName, clientWindow);
wmWindow = childWindow;
childWindow = clientWindow;
}
}
if ((source == sourceKey && childWindow != hRoot) ||
source == sourceId ||
source == sourceWd) {
if (childWindow == hRoot) {
xrect.x = 0;
xrect.y = 0;
xrect.width = DisplayWidth(hDisplay, hScreen);
xrect.height = DisplayHeight(hDisplay, hScreen);
}
else {
/* take the child window (and optional client/wm window info) and
* determine the portion of the root window that should be grabbed */
if (!XGetWindowAttributes(hDisplay, childWindow, &xwa)) {
fprintf(stderr, "%s: unable to get window coordinates\n", programName);
XCloseDisplay(hDisplay);
exit(3);
}
/* get the correct screen and root window for the selected window,
* and if it isn't the default, muck with the global state of the
* program a bit
*/
i = ScreenNumberOfScreen(xwa.screen);
if (i != hScreen) {
hRoot = xwa.root;
hScreen = i;
#ifndef NO_VIRTUAL_WINDOW
vRoot = VirtualRootWindow(hDisplay, hScreen);
#else
vRoot = hRoot;
#endif
depth = DefaultDepth(hDisplay, hScreen);
}
sourceWindow = vRoot;
if (!borders) {
xrect.x = 0;
xrect.y = 0;
xrect.width = xwa.width;
xrect.height = xwa.height;
}
else {
xrect.x = -xwa.border_width;
xrect.y = -xwa.border_width;
xrect.width = xwa.width + (2 * xwa.border_width);
xrect.height = xwa.height + (2 * xwa.border_width);
}
/* translate the rectangle coordinates to root-window coordinates */
if (!XTranslateCoordinates(hDisplay, childWindow, vRoot,
(int)(xrect.x), (int)(xrect.y), &x, &y, &ignored)) {
fprintf(stderr, "%s: unable to translate window coordinates\n", programName);
XCloseDisplay(hDisplay);
exit(3);
}
xrect.x = (short)x; /* why did they make rectangle coords shorts? */
xrect.y = (short)y;
if (hRoot == vRoot) {
/* do some clipping here, since it's cheap */
i = DisplayWidth(hDisplay, hScreen);
if (xrect.x + xrect.width > i) {
x = i - (int)(xrect.x);
if (x < 0) x = 0;
xrect.width = x;
}
i = DisplayHeight(hDisplay, hScreen);
if (xrect.y + xrect.height > i) {
x = i - (int)(xrect.y);
if (x < 0) x = 0;
xrect.height = x;
}
}
}
}
if (verbose)
fprintf(stderr, "%s: bounding box is [x=%d y=%d w=%d h=%d]\n", programName, xrect.x, xrect.y,
xrect.width, xrect.height);
/* sleep if asked to do so */
if (postSelectSleepSeconds) {
if (grabServer) {
XUngrabServer(hDisplay);
XSync(hDisplay, FALSE);
}
sleep(postSelectSleepSeconds);
if (grabServer)
XGrabServer(hDisplay);
}
/* get the image bounded by the rectangle from the source window */
if (!noBell)
XBell(hDisplay, 50);
if (!getImage(&xrect, &image, sourceWindow, childWindow)) {
XCloseDisplay(hDisplay);
exit(3);
}
if (grabServer)
XUngrabServer(hDisplay);
if (!noBell) {
XBell(hDisplay, 20);
XBell(hDisplay, 30);
}
XFlush(hDisplay);
/* do color image processing/conversions */
if (depth >= 2) {
if (brighten)
brightenColors(&image, brightenFactor);
if (doAnd)
alterPlanes(&image, TRUE, andBits);
if (doOr)
alterPlanes(&image, FALSE, orBits);
}
if (doReverse)
reverseColors(&image);
if (depth >= 2) {
if (! (preview && psColor) ) {
if (ForceBitmap) {
pixmap2bitmap(&image);
depth = 1;
}
else if (Halftone)
pixmap2halftone(&image, DitherKind);
else
compressColormap(&image);
}
else
compressColormap(&image);
}
/* open the output stream */
if (outfileName) {
outfile = fopen(outfileName, "w");
if (!outfile) {
fprintf(stderr, "%s: ", programName);
perror(outfileName);
exit(3);
}
/* form an image name based on the file name */
{
char *img = rindex(outfileName, '/');
if (img) strcpy(imageName, img + 1);
else strcpy(imageName, outfileName);
ptr = rindex(imageName, '.'); /* Drop the final extension */
if (ptr) *ptr = '\0';
}
}
else
strcpy(imageName,"unnamed");
/* write to the output stream in the requested format */
switch (outputFormat) {
case xwdFormat:
writeXWD(&image, outfile, xwdxy);
break;
case simpleFormat:
writeSimple(&image, outfile);
break;
case puzzleFormat:
writePuzzle(&image, outfile);
break;
case pixmapFormat:
if (image.ximage->depth <= 1)
writeXYPixmap(&image, outfile);
else
writeZPixmap(xpmFormat, &image, outfile);
break;
case psFormat:
default:
if (onlyEpsi)
writeOnlyPreview(&image, outfile);
else if (psColor && image.ximage->depth >= 2)
writeColorPS(&image, outfile, compress, encapsulate,
preview, landscape, binary, checkLimits);
else
writePostscript(&image, outfile, compress, encapsulate,
preview, landscape, binary, checkLimits);
break;
}
XDestroyImage(image.ximage);
XCloseDisplay(hDisplay);
if (outfileName)
fclose(outfile);
exit(0);
}
#ifndef NO_MAIN
main(argc, argv)
int argc;
char *argv[];
{
char *env;
env = (char *)getenv("XGRABSC");
xgrabsc(argc, argv, env);
}
#endif